#include <windows.h>
#include "tchddi.h"


HMODULE OrigDll = 0;

typedef BOOL (*TouchPanelGetDeviceCaps_t)(INT iIndex, LPVOID lpOutput);
typedef BOOL (*TouchPanelSetMode_t)(INT iIndex, LPVOID lpInput);
typedef void (*TouchPanelPowerHandler_t)(BOOL bOff);
typedef BOOL (*TouchPanelEnable_t)(PFN_TOUCH_PANEL_CALLBACK pfnCallback);
typedef VOID (*TouchPanelDisable_t)(VOID);
typedef BOOL (*TouchPanelReadCalibrationPoint_t)(INT *pRawX,INT *pRawY);
typedef VOID (*TouchPanelReadCalibrationAbort_t)(VOID);
typedef BOOL (*TouchPanelSetCalibration_t)(INT32 cCalibrationPoints,INT32 *pScreenXBuffer,INT32 *pScreenYBuffer,INT32 *pUncalXBuffer,INT32 *pUncalYBuffer);
typedef void (*TouchPanelCalibrateAPoint_t)(INT32 UncalX, INT32 UncalY, INT32 *pCalX, INT32 *pCalY);
typedef HWND (*TouchGetFocusWnd_t)();
typedef HWND (*TouchGetLastTouchFocusWnd_t)();
typedef void (*TouchReset_t)(BOOL bSetAllValuesToDefault);
typedef void (*TouchCreateEvent_t)(int iX, int iY);
typedef BOOL (*TouchRegisterWindow_t)(HWND hClientWnd);
typedef void (*TouchUnregisterWindow_t)(HWND hClientWnd);
typedef void (*TouchSetValue_t)(DWORD dwName, DWORD dwValue);
typedef LRESULT (*TouchGetValue_t)(DWORD dwName, DWORD dwValue);
typedef LPVOID (*TouchGetQueuePtr_t)();

TouchPanelGetDeviceCaps_t          OrigTouchPanelGetDeviceCaps;
TouchPanelSetMode_t                OrigTouchPanelSetMode;
TouchPanelPowerHandler_t           OrigTouchPanelPowerHandler;
TouchPanelEnable_t                 OrigTouchPanelEnable;
TouchPanelDisable_t                OrigTouchPanelDisable;
TouchPanelReadCalibrationPoint_t   OrigTouchPanelReadCalibrationPoint;
TouchPanelReadCalibrationAbort_t   OrigTouchPanelReadCalibrationAbort;
TouchPanelSetCalibration_t         OrigTouchPanelSetCalibration;
TouchPanelCalibrateAPoint_t        OrigTouchPanelCalibrateAPoint;
TouchGetFocusWnd_t                 OrigTouchGetFocusWnd;
TouchGetLastTouchFocusWnd_t        OrigTouchGetLastTouchFocusWnd;
TouchReset_t                       OrigTouchReset;
TouchCreateEvent_t                 OrigTouchCreateEvent;
TouchRegisterWindow_t              OrigTouchRegisterWindow;
TouchUnregisterWindow_t            OrigTouchUnregisterWindow;
TouchSetValue_t                    OrigTouchSetValue;
TouchGetValue_t                    OrigTouchGetValue;
TouchGetQueuePtr_t                 OrigTouchGetQueuePtr;

PFN_TOUCH_PANEL_CALLBACK OrigCallback;

DWORD LastUpTick = 0;
BOOL bad = false;


BOOL TouchCallback(TOUCH_PANEL_SAMPLE_FLAGS Flags, INT X, INT Y)
{
	BOOL down =  (Flags&TouchSampleValidFlag) &&
		         (Flags&TouchSampleDownFlag) &&
		        !(Flags&TouchSamplePreviousDownFlag);

	BOOL up   =  (Flags&TouchSampleValidFlag) &&
		        !(Flags&TouchSampleDownFlag) &&
		         (Flags&TouchSamplePreviousDownFlag);


	if (down)
	{
		DWORD tick = GetTickCount();
		DWORD diff = tick-LastUpTick;
		bad = (diff < 50);
		LastUpTick = tick;
	}

	if (up) LastUpTick = GetTickCount();

	return bad ? true : OrigCallback(Flags,X,Y);
}


extern "C" BOOL TouchPanelGetDeviceCaps(INT iIndex, LPVOID lpOutput)
{
	return OrigTouchPanelGetDeviceCaps(iIndex,lpOutput);
}

extern "C" BOOL TouchPanelSetMode(INT iIndex, LPVOID lpInput)
{
	return OrigTouchPanelSetMode(iIndex,lpInput);
}

extern "C" void TouchPanelPowerHandler(BOOL bOff)
{
	OrigTouchPanelPowerHandler(bOff);
}

extern "C" BOOL TouchPanelEnable(PFN_TOUCH_PANEL_CALLBACK pfnCallback)
{
	OrigCallback = pfnCallback;
	return OrigTouchPanelEnable(&TouchCallback);
}

extern "C" VOID TouchPanelDisable(VOID)
{
	OrigTouchPanelDisable();
}

extern "C" BOOL TouchPanelReadCalibrationPoint(INT *pRawX,INT *pRawY)
{
	return OrigTouchPanelReadCalibrationPoint(pRawX,pRawY);
}

extern "C" VOID TouchPanelReadCalibrationAbort(VOID)
{
	OrigTouchPanelReadCalibrationAbort();
}

extern "C" BOOL TouchPanelSetCalibration(INT32 cCalibrationPoints,INT32 *pScreenXBuffer,INT32 *pScreenYBuffer,INT32 *pUncalXBuffer,INT32 *pUncalYBuffer)
{
	return OrigTouchPanelSetCalibration(cCalibrationPoints,pScreenXBuffer,pScreenYBuffer,pUncalXBuffer,pUncalYBuffer);
}

extern "C" void TouchPanelCalibrateAPoint(INT32 UncalX, INT32 UncalY, INT32 *pCalX, INT32 *pCalY)
{
	OrigTouchPanelCalibrateAPoint(UncalX,UncalY,pCalX,pCalY);
}


extern "C" HWND TouchGetFocusWnd()
{
	if (!OrigTouchGetFocusWnd) return 0;
	return OrigTouchGetFocusWnd();
}

extern "C" HWND TouchGetLastTouchFocusWnd()
{
	if (!OrigTouchGetLastTouchFocusWnd) return 0;
	return OrigTouchGetLastTouchFocusWnd();
}

extern "C" void TouchReset(BOOL bSetAllValuesToDefault)
{
	if (!OrigTouchReset) return;
	OrigTouchReset(bSetAllValuesToDefault);
}

extern "C" void TouchCreateEvent(int iX, int iY)
{
	if (!OrigTouchCreateEvent) return;
	OrigTouchCreateEvent(iX,iY);
}

extern "C" BOOL TouchRegisterWindow(HWND hClientWnd)
{
	if (!OrigTouchRegisterWindow) return 0;
	return OrigTouchRegisterWindow(hClientWnd);
}

extern "C" void TouchUnregisterWindow(HWND hClientWnd)
{
	if (!OrigTouchUnregisterWindow) return;
	OrigTouchUnregisterWindow(hClientWnd);
}

extern "C" void TouchSetValue(DWORD dwName, DWORD dwValue)
{
	if (!OrigTouchSetValue) return;
	OrigTouchSetValue(dwName,dwValue);
}

extern "C" LRESULT TouchGetValue(DWORD dwName, DWORD dwValue)
{
	if (!OrigTouchGetValue) return 0;
	return OrigTouchGetValue(dwName,dwValue);
}

extern "C" LPVOID TouchGetQueuePtr()
{
	if (!OrigTouchGetQueuePtr) return 0;
	return OrigTouchGetQueuePtr();
}

extern "C" HINSTANCE LoadDriver(LPCWSTR lpszFileName);//defined in pkfuncs.h

BOOL DllMain(HANDLE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{

    switch (fdwReason)
    {
		case DLL_PROCESS_ATTACH: {
            DisableThreadLibraryCalls((HMODULE) hinstDll);
#ifdef DBG_LOG
			LogFile = CreateFile(L"\\TouchECLog.txt",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL/* | FILE_FLAG_WRITE_THROUGH*/,NULL);
			SetFilePointer(LogFile,0,NULL,FILE_END);
#endif
			WCHAR origdll[64] = L"touch.dll";

			OrigDll = LoadDriver(origdll);
			if (!OrigDll) return FALSE;

			if (!(OrigTouchPanelGetDeviceCaps        = (TouchPanelGetDeviceCaps_t        ) GetProcAddress(OrigDll,L"TouchPanelGetDeviceCaps"))) return FALSE;
			if (!(OrigTouchPanelSetMode              = (TouchPanelSetMode_t              ) GetProcAddress(OrigDll,L"TouchPanelSetMode"))) return FALSE;
			if (!(OrigTouchPanelPowerHandler         = (TouchPanelPowerHandler_t         ) GetProcAddress(OrigDll,L"TouchPanelPowerHandler"))) return FALSE;
			if (!(OrigTouchPanelEnable               = (TouchPanelEnable_t               ) GetProcAddress(OrigDll,L"TouchPanelEnable"))) return FALSE;
			if (!(OrigTouchPanelDisable              = (TouchPanelDisable_t              ) GetProcAddress(OrigDll,L"TouchPanelDisable"))) return FALSE;
			if (!(OrigTouchPanelReadCalibrationPoint = (TouchPanelReadCalibrationPoint_t ) GetProcAddress(OrigDll,L"TouchPanelReadCalibrationPoint"))) return FALSE;
			if (!(OrigTouchPanelReadCalibrationAbort = (TouchPanelReadCalibrationAbort_t ) GetProcAddress(OrigDll,L"TouchPanelReadCalibrationAbort"))) return FALSE;
			if (!(OrigTouchPanelSetCalibration       = (TouchPanelSetCalibration_t       ) GetProcAddress(OrigDll,L"TouchPanelSetCalibration"))) return FALSE;
			if (!(OrigTouchPanelCalibrateAPoint      = (TouchPanelCalibrateAPoint_t      ) GetProcAddress(OrigDll,L"TouchPanelCalibrateAPoint"))) return FALSE;
			OrigTouchGetFocusWnd               = (TouchGetFocusWnd_t               ) GetProcAddress(OrigDll,L"TouchGetFocusWnd");
			OrigTouchGetLastTouchFocusWnd      = (TouchGetLastTouchFocusWnd_t      ) GetProcAddress(OrigDll,L"TouchGetLastTouchFocusWnd");
			OrigTouchReset                     = (TouchReset_t                     ) GetProcAddress(OrigDll,L"TouchReset");
			OrigTouchCreateEvent               = (TouchCreateEvent_t               ) GetProcAddress(OrigDll,L"TouchCreateEvent");
			OrigTouchRegisterWindow            = (TouchRegisterWindow_t            ) GetProcAddress(OrigDll,L"TouchRegisterWindow");
			OrigTouchUnregisterWindow          = (TouchUnregisterWindow_t          ) GetProcAddress(OrigDll,L"TouchUnregisterWindow");
			OrigTouchSetValue                  = (TouchSetValue_t                  ) GetProcAddress(OrigDll,L"TouchSetValue");
			OrigTouchGetValue                  = (TouchGetValue_t                  ) GetProcAddress(OrigDll,L"TouchGetValue");
			OrigTouchGetQueuePtr               = (TouchGetQueuePtr_t               ) GetProcAddress(OrigDll,L"TouchGetQueuePtr");
			break;
		}
		case DLL_PROCESS_DETACH: {
			if (OrigDll) FreeLibrary(OrigDll);
            break;
		}
    }
    return TRUE;
}
